export default class River {
	constructor() {
		this.particles = [];
		this.nums;
		this.particleDensity = 4000;
		this.noiseScale = 800;
		this.maxLife = 10;
		this.simulationSpeed = 0.2;
		this.fadeFrame = 0;
		this.backgroundColor;
		this.visualMode = 0;
		this.numModes = 4;
		this.invertColors = false;
	}

	setup(sk, w, h) {
		this.nums = w * h / this.particleDensity;
		this.backgroundColor = sk.color(20, 20, 20);
		sk.createCanvas(w, h);
		sk.background(this.backgroundColor);
		for (let i = 0; i < this.nums; i++) {
			this.particles[i] = new Particle(sk, this.maxLife);
		}
	}


	draw(sk) {
		sk.noStroke();

		++this.fadeFrame;
		if (this.fadeFrame % 5 == 0) {
			if (this.invertColors) {
				sk.blendMode(sk.ADD);
			} else {
				sk.blendMode(sk.DIFFERENCE);
			}
			sk.fill(1, 1, 1);
			sk.rect(0, 0, sk.width, sk.height);

			if (this.invertColors) {
				sk.blendMode(sk.DARKEST);
			} else {
				sk.blendMode(sk.LIGHTEST);
			}
			sk.fill(this.backgroundColor);
			sk.rect(0, 0, sk.width, sk.height);
		}

		sk.blendMode(sk.BLEND);
		sk.smooth();
		for (let i = 0; i < this.nums; i++) {
			let iterations = sk.map(i, 0, this.nums, 5, 1);
			let radius = sk.map(i, 0, this.nums, 2, 6);

			this.particles[i].move(sk, iterations, this.noiseScale, this.simulationSpeed, this.maxLife);
			this.particles[i].checkEdge(sk, this.maxLife);

			var alpha = 255;
			var particleColor;
			var fadeRatio;
			fadeRatio = sk.min(this.particles[i].life * 5 / this.maxLife, 1);
			fadeRatio = sk.min((this.maxLife - this.particles[i].life) * 5 / this.maxLife, fadeRatio);
			var colorCase = this.visualMode;
			if (this.visualMode == 0) {
				colorCase = sk.int(this.particles[i].pos.x / sk.width * 3) + 1;
			}
			switch (colorCase) {
				case 1:
					var lifeRatioGrayscale = sk.min(255, (255 * this.particles[i].life / this.maxLife) + sk.red(this
						.backgroundColor));
					particleColor = sk.color(lifeRatioGrayscale, alpha * fadeRatio);
					break;
				case 2:
					particleColor = this.particles[i].color;
					break;
				case 3:
					particleColor = sk.color(sk.blue(this.particles[i].color) + 70, sk.green(this.particles[i]
						.color) + 20, sk.red(
						this.particles[i].color) - 50);
					break;
			}
			if (this.invertColors) {
				particleColor = sk.color(255 - sk.red(particleColor), 255 - sk.green(particleColor), 255 - sk.blue(
					particleColor));
			}
			sk.fill(sk.red(particleColor), sk.green(particleColor), sk.blue(particleColor), alpha * fadeRatio);
			this.particles[i].display(sk, radius);
		}
	}

	wr(sk) {}
	kr(sk) {
		this.visualMode = ++this.visualMode % this.numModes;
		if (this.visualMode == 0) {
			this.invertColors = !this.invertColors;
			this.backgroundColor = this.invertColors ? sk.color(235, 235, 235) : sk.color(20, 20, 20);
		}
		sk.noiseSeed(sk.random() * Number.MAX_SAFE_INTEGER);
		sk.background(this.backgroundColor);
		for (var i = 0; i < this.nums; i++) {
			this.particles[i].respawn(sk);
			this.particles[i].life = sk.random(0, this.maxLife);
		}
	}
	kp(sk) {}
	mp(sk) {}
	mr(sk) {}
	mv(sk) {}
	mw(sk, e) {}

}

class Particle {
	constructor(sk, maxLife) {
		this.vel = sk.createVector(0, 0);
		this.pos = sk.createVector(sk.random(0, sk.width), sk.random(0, sk.height));
		this.life = sk.random(0, maxLife);
		this.flip = sk.int(sk.random(0, 2)) * 2 - 1;
		let c = [sk.color(110, 57, 204), sk.color(7, 153, 242), sk.color(255, 255, 255)]
		this.color = c[sk.int(sk.random(0, 3))]

	}
	// member properties and initialization


	// member functions
	move(sk, iterations, noiseScale, simulationSpeed, maxLife) {
		if ((this.life -= 0.01666) < 0)
			this.respawn(sk, maxLife);
		while (iterations > 0) {
			let angle = sk.noise(this.pos.x / noiseScale, this.pos.y / noiseScale) * sk.TWO_PI * noiseScale * this
				.flip;
			this.vel.x = sk.cos(angle);
			this.vel.y = sk.sin(angle);
			this.vel.mult(simulationSpeed);
			this.pos.add(this.vel);
			--iterations;
		}
	}

	checkEdge(sk, maxLife) {
		if (this.pos.x > sk.width || this.pos.x < 0 || this.pos.y > sk.height || this.pos.y < 0) {
			this.respawn(sk, maxLife);
		}
	}

	respawn(sk, maxLife) {
		this.pos.x = sk.random(0, sk.width);
		this.pos.y = sk.random(0, sk.height);
		this.life = maxLife;
	}

	display(sk, r) {
		sk.ellipse(this.pos.x, this.pos.y, r, r);
	}
}
